home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / primitives.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-16  |  59.7 KB  |  1,959 lines

  1. /*
  2.  * @(#)primitives.c    1.12  1/20/89
  3.  */
  4. #include "datadesc.h"
  5. #include "builtins.h"
  6. #include "error.h"
  7. #include "nodes.h"
  8. #include "regdefs.h"
  9. #include "genutils.h"
  10. #include "emit.h"
  11. #include "consts.h"
  12. #include "evaluate.h"
  13. #include "primitives.h"
  14. #include "system.h"
  15. #include "trace.h"
  16.  
  17. NodePtr theNode = NULL;
  18. extern char *codeFileName;
  19. Boolean formatAs0r = FALSE;
  20.  
  21. static void unimplementedPrimitive(opIndex, typeIndex)
  22. int opIndex, typeIndex;
  23. {
  24.   emit("Primitive %d of type %d\n", opIndex, typeIndex);
  25.   ErrorMessage(theNode, "Unimplemented primitive %d of type %d", opIndex, typeIndex);
  26. }
  27.  
  28. void implementationBug(string)
  29. char *string;
  30. {
  31.   emit("Implementation bug (%s): %s\n", codeFileName, string);
  32.   ErrorMessage(theNode, "Implementation bug (%s): %s", codeFileName, string);
  33. }
  34.  
  35. #define SELF 1
  36. #define ARG1 2
  37. #define ARG2 4
  38. #define ARG3 8
  39. #define S SELF
  40. #define S1 (SELF | ARG1)
  41. #define S12 (SELF | ARG1 | ARG2)
  42. #ifdef vax
  43. #define T FALSE
  44. #endif
  45. #ifdef sun
  46. #define T TRUE
  47. #endif
  48. #define F FALSE
  49.  
  50. PrimitiveDesc primitives[] =
  51. {
  52. /* None for abstract type */
  53. /* None for any */
  54. /* Array 1 */
  55.   {   2, TRUE , ANYINDEX, INTEGERINDEX, NILINDEX, "getElement", F, 0 },
  56.   { 102, FALSE, INTEGERINDEX, ANYINDEX, NILINDEX, "setElement", F, 0 },
  57.   { 202, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "upb", F, 0 },
  58.   { 302, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "lwb", F, 0 },
  59.   { 402, TRUE , ANYINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
  60.   { 502, FALSE, INTEGERINDEX, INTEGERINDEX, ANYINDEX, "setSlice", F, 0 },
  61.   { 602, FALSE, INTEGERINDEX, NILINDEX, NILINDEX, "slideTo", F, 0 },
  62.   { 702, FALSE, ANYINDEX, NILINDEX, NILINDEX, "addUpper", F, 0 },
  63.   { 802, TRUE , ANYINDEX, NILINDEX, NILINDEX, "removeUpper", F, 0 },
  64.   { 902, FALSE, ANYINDEX, NILINDEX, NILINDEX, "addLower", F, 0 },
  65.   {1002, TRUE , ANYINDEX, NILINDEX, NILINDEX, "removeLower", F, 0 },
  66.   {1102, TRUE , BOOLEANINDEX, NILINDEX, NILINDEX, "empty", F, 0 },
  67.   {1202, TRUE , ANYINDEX, ANYINDEX, NILINDEX, "catenate", F, 0 },
  68. /* Boolean 3 */
  69.   {   3, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, ">", F, 0 },
  70.   { 103, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, ">=", F, 0 },
  71.   { 203, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "<", F, 0 },
  72.   { 303, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "<=", F, 0 },
  73.   { 403, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "=", F, 0 },
  74.   { 503, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "!=", F, 0 },
  75.   { 603, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "&", F, S1 },
  76.   { 703, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "|", F, S1 },
  77.   { 803, TRUE , BOOLEANINDEX, NILINDEX, NILINDEX, "!", F, S },
  78.   { 903, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
  79. /* Character 4 */
  80.   {   4, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, ">", F, 0 },
  81.   { 104, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, ">=", F, 0 },
  82.   { 204, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "<", F, 0 },
  83.   { 304, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "<=", F, 0 },
  84.   { 404, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "=", F, 0 },
  85.   { 504, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "!=", F, 0 },
  86.   { 604, TRUE , STRINGINDEX,  NILINDEX,       NILINDEX, "asString", F, 0 },
  87.   { 704, TRUE , INTEGERINDEX, NILINDEX,       NILINDEX, "ord", F, 0 },
  88.   { 804, TRUE , CHARACTERINDEX,INTEGERINDEX,  NILINDEX, "literal", F, 0 },
  89. /* Condition 5 */
  90.   {   5, TRUE , CONDITIONINDEX, NILINDEX, NILINDEX, "create on type", F, 0 },
  91. /* Integer 6 */
  92.   {   6, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "+", F, S1 },
  93.   { 106, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "-", F, S1 },
  94.   { 206, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "*", T, S1 },
  95.   { 306, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "/", T, S1 },
  96.   { 406, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "#", T, S1 },
  97.   { 506, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, ">", F, 0 },
  98.   { 606, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, ">=", F, 0 },
  99.   { 706, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "<", F, 0 },
  100.   { 806, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "<=", F, 0 },
  101.   { 906, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "=", F, 0 },
  102.   {1006, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "!=", F, 0 },
  103.   {1106, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
  104.   {1206, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "~", F, S },
  105.   {1306, TRUE , REALINDEX, NILINDEX, NILINDEX, "asReal", F, S },
  106. /* None for NIL 7 */
  107. /* Node 8 */
  108.   {   8, FALSE, TIMEINDEX, NILINDEX, NILINDEX, "delay", F, 0 },
  109.   { 108, FALSE, TIMEINDEX, NILINDEX, NILINDEX, "waitUntil", F, 0 },
  110.   { 208, TRUE , NODELISTINDEX, NILINDEX, NILINDEX, "getActiveNodes", F, 0 },
  111.   { 308, TRUE , NODELISTINDEX, NILINDEX, NILINDEX, "getAllNodes", F, 0 },
  112.   { 408, TRUE , NODELISTELEMENTINDEX, NODEINDEX, NILINDEX, "getNodeInformation", F, 0 },
  113.   { 508, FALSE, ANYINDEX, NILINDEX, NILINDEX, "setNodeEventHandler", F, 0 },
  114.   { 608, FALSE, ANYINDEX, NILINDEX, NILINDEX, "setNodeEventHandler", F, 0 },
  115.   { 708, TRUE , INSTREAMINDEX, NILINDEX, NILINDEX, "getStdin", F, 0 },
  116.   { 808, TRUE , OUTSTREAMINDEX, NILINDEX, NILINDEX, "getStdout", F, 0 },
  117.   { 908, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "getName", F, 0 },
  118.   {2008, TRUE , INSTREAMINDEX, NILINDEX, NILINDEX, "getStdin  on node itself", F, 0 },
  119.   {2108, TRUE , OUTSTREAMINDEX, NILINDEX, NILINDEX, "getStdout on node itself", F, 0 },
  120.   {3008, FALSE, ANYINDEX, NILINDEX, NILINDEX, "EMXNextEvent", F, 0 },
  121. /* None for signature 9 */
  122. /* Real 10 */
  123.   {  10, TRUE , REALINDEX, REALINDEX, NILINDEX, "+", F, S1 },
  124.   { 110, TRUE , REALINDEX, REALINDEX, NILINDEX, "-", F, S1 },
  125.   { 210, TRUE , REALINDEX, REALINDEX, NILINDEX, "*", F, S1 },
  126.   { 310, TRUE , REALINDEX, REALINDEX, NILINDEX, "/", F, S1 },
  127.   { 410, TRUE , REALINDEX, REALINDEX, NILINDEX, "#", F, S1 },
  128.   { 510, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, ">", F, 0 },
  129.   { 610, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, ">=", F, 0 },
  130.   { 710, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "<", F, 0 },
  131.   { 810, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "<=", F, 0 },
  132.   { 910, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "=", F, 0 },
  133.   {1010, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "!=", F, 0 },
  134.   {1110, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
  135.   {1210, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "asInteger", F, S },
  136.   {1310, TRUE , REALINDEX, NILINDEX, NILINDEX, "~", T, S },
  137. /* String 11 */
  138.   {  11, TRUE , CHARACTERINDEX, INTEGERINDEX, NILINDEX, "getElement", F, ARG1 },
  139.   { 111, TRUE , STRINGINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
  140.   { 211, TRUE , STRINGINDEX, STRINGINDEX, NILINDEX, "||", F, 0 },
  141.   { 311, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
  142.   { 411, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, ">", F, 0 },
  143.   { 511, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, ">=", F, 0 },
  144.   { 611, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "<", F, 0 },
  145.   { 711, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "<=", F, 0 },
  146.   { 811, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "=", F, 0 },
  147.   { 911, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "!=", F, 0 },
  148.   {1011, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "length", F, 0 },
  149.   {1111, FALSE, INTEGERINDEX, CHARACTERINDEX, NILINDEX, "lowlevelsleazysetElement", F, 0 },
  150. /* Vector 12 */
  151.   {  12, TRUE , ANYINDEX, INTEGERINDEX, NILINDEX, "getElement", F, 0 },
  152.   { 112, FALSE, INTEGERINDEX, ANYINDEX, NILINDEX, "setElement", F, 0 },
  153.   { 212, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "upb", F, 0 },
  154.   { 312, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "lwb", F, 0 },
  155.   { 412, TRUE , ANYINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
  156.   { 512, FALSE, INTEGERINDEX, INTEGERINDEX, ANYINDEX, "setSlice", F, 0 },
  157.   { 612, TRUE , ANYINDEX, ANYINDEX, NILINDEX, "catenate", F, 0 },
  158.   { 2012, TRUE , ANYINDEX, INTEGERINDEX, NILINDEX, "getElement", F, 0 },
  159.   { 2112, FALSE, INTEGERINDEX, ANYINDEX, NILINDEX, "setElement", F, 0 },
  160.   { 2212, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "upb", F, 0 },
  161.   { 2312, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "lwb", F, 0 },
  162.   { 2412, TRUE , ANYINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
  163.   { 2512, FALSE, INTEGERINDEX, INTEGERINDEX, ANYINDEX, "setSlice", F, 0 },
  164.   { 2612, TRUE , ANYINDEX, ANYINDEX, NILINDEX, "catenate", F, 0 },
  165. /* Time 13 */
  166.   {  13, TRUE , TIMEINDEX, TIMEINDEX, NILINDEX, "+", F, 0 },
  167.   { 113, TRUE , TIMEINDEX, TIMEINDEX, NILINDEX, "-", F, 0 },
  168.   { 213, TRUE , TIMEINDEX, INTEGERINDEX, NILINDEX, "*", F, 0 },
  169.   { 313, TRUE , TIMEINDEX, INTEGERINDEX, NILINDEX, "/", F, 0 },
  170.   { 413, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, ">", F, 0 },
  171.   { 513, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, ">=", F, 0 },
  172.   { 613, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "<", F, 0 },
  173.   { 713, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "<=", F, 0 },
  174.   { 813, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "=", F, 0 },
  175.   { 913, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "!=", F, 0 },
  176.   {1013, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "getSeconds", F, 0 },
  177.   {1113, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "getMicroSeconds", F, 0 },
  178.   {1213,  TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
  179.   {1313,  TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asDate", F, 0 },
  180. /* none for NodeListElement 14 */
  181. /* none for NodeList 15 */
  182. /* InStream 16 */
  183.   {  16, TRUE , INTEGERINDEX, INTEGERINDEX, ANYINDEX, "read", F, 0 },
  184.   { 116, FALSE, INTEGERINDEX, NILINDEX, NILINDEX, "close", F, 0 },
  185. /* OutStream 17 */
  186.   {  17, FALSE, INTEGERINDEX, ANYINDEX, INTEGERINDEX, "write", F, 0 },
  187.   { 117, FALSE, INTEGERINDEX, NILINDEX, NILINDEX, "closeOutStream", F, 0 },
  188. /* ImmutableVector 18, uses vector ops */
  189. /* BitChunk 19 */
  190.   {  19, TRUE,  INTEGERINDEX, INTEGERINDEX, INTEGERINDEX, "getSigned", T, S12 },
  191.   { 119, TRUE,  INTEGERINDEX, INTEGERINDEX, INTEGERINDEX, "getUnsigned", T, S12 },
  192.   { 219, FALSE, INTEGERINDEX, INTEGERINDEX, INTEGERINDEX, "setSigned", F, 0 },
  193.   { 319, TRUE,  INTEGERINDEX, NILINDEX,     NILINDEX,     "addr", T, S1 },
  194. /* ownName and ownType */
  195.   { 199, TRUE,  STRINGINDEX, NILINDEX, NILINDEX, "ownName", F, 0 },
  196.   { 299, TRUE,  SIGNATUREINDEX, NILINDEX, NILINDEX, "ownType", F, 0 },
  197. /* Dummy at the end */
  198.   {   0, FALSE, NILINDEX, NILINDEX, NILINDEX, NULL, F, 0 }
  199. };
  200.  
  201. char *primOpName(typeIndex, opIndex)
  202. int typeIndex, opIndex;
  203. {
  204.   int realIndex = typeIndex + opIndex * 100;
  205.   register PrimitiveDesc *p = primitives;
  206.   while (p->number != realIndex && p->number != 0) p++;
  207.   assert(p->number != 0);
  208.   return(p->name);
  209. }
  210.  
  211. Variable *forceIntoRegister(v, brand)
  212. Variable *v;
  213. Brand brand;
  214. {
  215.   Variable result;
  216.   if (isAppropriateRegister(v->data, brand)) {
  217.     /* do nothing */
  218.   } else {
  219.     result.data.kind = DD_Address;
  220.     result.data.value.address = nullAddress;
  221.     result.data.value.address.base = Register;
  222.     result.data.value.address.baseIsTemporary = TRUE;
  223.     result.data.value.address.offset = forceAllocateReg(1, brand, 2);
  224.     if (result.data.value.address.offset == -1) {
  225.       implementationBug("Out of temporary registers");
  226.     }
  227.     result.abCon.kind = DD_AbCon;
  228.     setDDAbstractType(result.abCon, getDDAbstractType(v->abCon));
  229.     setDDConcreteType(result.abCon,
  230.       brand == DataBrand ?
  231.     OIDOfBuiltin(B_INSTCT, INTEGERINDEX) :
  232.     OIDOfBuiltin(B_INSTCT, STRINGINDEX));
  233.     ddGenerateAssign(result.data, result.abCon, v->data, v->abCon);
  234.     *v = result;
  235.   }
  236.   return(v);
  237. }
  238.  
  239. /*
  240.  * Generate a compare, return whether you had to reverse the sense of the
  241.  * compare.
  242.  */
  243. DD generateCompare(left, right, size, cond)
  244. Variable *left, *right;
  245. char size;
  246. PSLCondition cond;
  247. {
  248.   DD result, inter;
  249. #ifdef sun
  250.   Variable *myleft = right, *myright = left;
  251. #endif
  252. #ifdef vax
  253.   Variable *myleft = left, *myright = right;
  254. #endif
  255.   if (isManifestDD(left->data) && isManifestDD(right->data)) {
  256.     /* figure the result */
  257.     int sign, answer;
  258.     if (left->data.kind == DD_RealManifest) {
  259.       double diff, atof();
  260.       diff = atof(left->data.value.realmanifest) - atof(right->data.value.realmanifest);
  261.       sign = diff == 0.0 ? 0 : diff < 0.0 ? -1 : 1;
  262.     } else {
  263.       int diff = left->data.value.manifest - right->data.value.manifest;
  264.       sign = diff == 0.0 ? 0 : diff < 0.0 ? -1 : 1;
  265.     }
  266.     switch (cond) {
  267.       case NEQ:
  268.     answer = sign != 0;
  269.     break;
  270.       case EQL:
  271.     answer = sign == 0;
  272.     break;
  273.       case GTR:
  274.     answer = sign > 0;
  275.     break;
  276.       case LEQ:
  277.     answer = sign <= 0;
  278.     break;
  279.       case GEQ:
  280.     answer = sign >= 0;
  281.     break;
  282.       case VS:
  283.     answer = FALSE;
  284.     break;
  285.       case VC:
  286.     answer = TRUE;
  287.     break;
  288.       case PL:
  289.     answer = sign >= 0;
  290.     break;
  291.       case MI:
  292.     answer = sign < 0;
  293.     break;
  294.       case ALWAYS:
  295.     answer = TRUE;
  296.     break;
  297.       default:
  298.     assert(FALSE);
  299.     break;
  300.     }
  301.     return(buildManifestDD(answer));
  302.   }
  303.   if (myleft->data.kind == DD_Self) {
  304.     assert(FALSE);
  305.   }
  306. #ifdef sun
  307.   if (size != 'f') {
  308.     if (isManifestDD(myleft->data) || isRegisterDD(myright->data)) {
  309.       /* we are laughing */
  310.     } else if (isManifestDD(myright->data) || isRegisterDD(myleft->data)) {
  311.       Variable *temp;
  312.       cond = reversedConditions[(int)cond];
  313.       temp = myleft;
  314.       myleft = myright;
  315.       myright = temp;
  316.     } else {
  317.       inter = buildRegisterDD(forceAllocateReg(1, DataBrand, 2));
  318.       emitMove(myright->data, inter, 'l');
  319.       FREEDD(myright->data);
  320.       myright->data = inter;
  321.     }
  322.   }
  323. #endif
  324. #ifdef vax
  325.   if (1) {
  326. #endif
  327. #ifdef sun
  328.   if (size != 'f') {
  329. #endif
  330.     emit("\tcmp%c\t", size);
  331.     writeDD(myleft->data, ',');
  332.     writeDD(myright->data, '\n');
  333. #ifdef sun
  334.   } else {
  335.     if (isAddressRegister(myright->data)) {
  336.       inter = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
  337.       emitMove(myright->data, inter, 'l');
  338.       FREEDD(myright->data);
  339.       myright->data = inter;
  340.     }
  341.     formatAs0r = TRUE;
  342.     emit("\tfmoves\t");
  343.     writeDD(myright->data, ',');
  344.     emit("fp0\n\tf%ss\t", "cmp");
  345.     writeDD(myleft->data, ',');
  346.     emit("fp0\n");
  347.     formatAs0r = FALSE;
  348. #endif
  349.   }
  350.   result.kind = DD_PSLCondition;
  351.   result.value.condition.psl = cond;
  352.   result.value.condition.isFloat = (size == 'f');
  353.   return(result);
  354. }
  355.  
  356. static void checkRange(self, arg1, isString, upb)
  357. Variable *self, *arg1;
  358. Boolean isString;
  359. int upb;
  360. {
  361.   int okLabel = nextLabelNumber++;
  362.   DD result;
  363.   Variable newself;
  364.  
  365.   newself = *self;
  366.   newself.data = increaseIndirection(newself.data);
  367.   newself.data.value.address.offset = upb;
  368.  
  369.   result = generateCompare(&newself, arg1, 'l', isString ? GTRU : GEQU);
  370.   vPushDD(result, buildConCon(BOOLEANINDEX));
  371.   generateBranch(TRUE, okLabel);
  372.   generateKernelCall("em_assertionFailure");
  373.   emit("L_%d:\n", okLabel);
  374. }
  375.  
  376. DD getScratch(brand, depth)
  377. Brand brand;
  378. int depth;
  379. {
  380.   DD s;
  381.   s.kind = DD_Address;
  382.   s.value.address = nullAddress;
  383.   s.value.address.base = Register;
  384.   s.value.address.offset = forceAllocateReg(1, brand, depth);
  385.   if (s.value.address.offset == -1) {
  386.     implementationBug("Out of temporary regs");
  387.     s.value.address.offset = 0;
  388.   }
  389.   s.value.address.baseIsTemporary = TRUE;
  390.   return(s);
  391. }
  392.  
  393. void freeScratch(s)
  394. DD s;
  395. {
  396.   assert(s.value.address.baseIsTemporary);
  397.   freeReg((unsigned)s.value.address.offset, 1);
  398. }
  399.  
  400. void do2OpAdd(result, other, datatype)
  401. DD result, other;
  402. char datatype;
  403. {
  404. #ifdef sun
  405.   assert(FALSE);
  406. #endif
  407.   if (other.kind == DD_Manifest && other.value.manifest == 0) {
  408.     /* do nothing */
  409.   } else if (other.kind == DD_RealManifest &&
  410.       atof(other.value.realmanifest) == 0.0) {
  411.     /* do nothing */
  412.   } else if (datatype == 'l' && other.kind == DD_Manifest && other.value.manifest == 1) {
  413.     emit("\tincl\t");
  414.     writeDD(result, '\n');
  415.   } else if (datatype == 'l' && other.kind == DD_Manifest && other.value.manifest == -1) {
  416.     emit("\tdecl\t");
  417.     writeDD(result, '\n');
  418.   } else {
  419.     emit("\tadd%c2\t", datatype);
  420.     writeDD(other, ',');
  421.     writeDD(result, '\n');
  422.   }
  423. }
  424.  
  425. PSLCondition compareCs[] = { GTR, GEQ, LSS, LEQ, EQL, NEQ };
  426. PSLCondition unsignedCompareCs[] = { GTRU, GEQU, LSSU, LEQU, EQL, NEQ };
  427. char *timeOpNames[] = {
  428.   "plus",
  429.   "minus",
  430.   "times",
  431.   "divide"
  432. };
  433.  
  434. /*
  435.  * Take care of Suns strange operands for most instructions.  Move one or
  436.  * the other of the operands to the result, return the other one, and make
  437.  * sure that "op other,result" will be legal.  I.e., if result is memory,
  438.  * other must be in a register.  Note that the abcon must be assigned first
  439.  * if result is on the stack.
  440.  */
  441.  
  442. void prepareForSunOp(left, right, result, commutative, tOther, tResult)
  443. Variable *left, *right, *result, **tOther, *tResult;
  444. Boolean commutative;
  445. {
  446.   Variable *other;
  447.   Brand brand = abConToBrand(result->abCon);
  448.   DD inter;
  449.   *tResult = *result;
  450.   if (isSameDD(left->data, result->data)) {
  451.     other = right;
  452.   } else if (commutative && isSameDD(right->data, result->data)) {
  453.     other = left;
  454.   } else {
  455.     emitMove(left->data, result->data, 'l');
  456.     other = right;
  457.     if (isPush(result->data)) {
  458.       tResult->data = buildAddressDD(regs_sp, 0);
  459.     }
  460.   }
  461.   if (isMemory(result->data) &&
  462.       !isAppropriateRegister(other->data, brand) &&
  463.       !isManifestDD(other->data)) {
  464.     /* move it to the appropriate register */
  465.     inter = buildRegisterDD(forceAllocateReg(1, brand, 2));
  466.     emitMove(other->data, inter, 'l');
  467.     FREEDD(other->data);
  468.     other->data = inter;
  469.   }
  470.   *tOther = other;
  471. }
  472.  
  473. extern Boolean maybeClaimReg();
  474. extern void moveDataToRegister(), moveVariableToRegisters(), claimReg();
  475. extern void ddGenerateMovqAssign();
  476.  
  477. int indexSize;
  478.  
  479. void doSunRealOp(left, right, op, result)
  480. DD left, right, result;
  481. char *op;
  482. {
  483.   DD nleft, nright;
  484.   nleft = nullDD; nright = nullDD;
  485.   if (isAddressRegister(left)) {
  486.     nleft = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
  487.     emitMove(left, nleft, 'l');
  488.     left = nleft;
  489.   }
  490.   if (isAddressRegister(right)) {
  491.     nright = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
  492.     emitMove(right, nright, 'l');
  493.     right = nright;
  494.   }
  495.   formatAs0r = TRUE;
  496.   emit("\tfmoves\t");
  497.   writeDD(left, ',');
  498.   emit("fp0\n\tf%ss\t", op);
  499.   writeDD(right, ',');
  500.   emit("fp0\n\tfmoves\tfp0,");
  501.   writeDD(result, '\n');
  502.   formatAs0r = FALSE;
  503.   FREEDD(nleft);
  504.   FREEDD(nright);
  505. }
  506.  
  507. void generateAMachineLanguagePrimitive(theObject, node, pn, self, nargs,
  508.               isExpression, c)
  509. NodePtr theObject, node;
  510. int pn;
  511. Variable *self;
  512. int nargs;
  513. Boolean isExpression;
  514. Context c;
  515. {
  516.   register int typeIndex, opIndex;
  517.   int resultRegister, elementTypeSize, stackAddress, tempReg;
  518.   char buffer[32];
  519.   Variable result, *arg1, *arg2, *arg3, *elementv, *other, tResult, temp;
  520.   DD element, scratch, anabcon;
  521.   DD elementAbCon;
  522.   NodePtr ct;
  523.   Symbol elementTypeSymbol;
  524.   Boolean knowResult, abConNeedsAssigning, reversed, needsFreeing;
  525.   PSLCondition cond;
  526.   Brand brand = DataBrand;
  527.   PrimitiveDescPtr pdp;
  528.  
  529.   theNode = node;
  530.   if (nargs == 0) {
  531.   } else if (nargs == 1) {
  532.     arg1 = vPeek(0);
  533.   } else if (nargs == 2) {
  534.     arg1 = vPeek(1);
  535.     arg2 = vPeek(0);
  536.   } else if (nargs == 3) {
  537.     arg1 = vPeek(2);
  538.     arg2 = vPeek(1);
  539.     arg3 = vPeek(0);
  540.   } else assert(FALSE);
  541.   typeIndex = pn % 100;
  542.   opIndex = pn / 100;
  543.   assert(typeIndex == 99 || typeIndex < NUMBUILTINS);
  544.   /*
  545.    * Cheat for now on register allocation.
  546.    */
  547.   for (pdp = primitives; pdp->number != pn && pdp->number != 0; pdp++) ;
  548.   assert(pdp->number == pn);
  549.  
  550.   if (pdp->isFunction) {
  551.     brand = oidToBrand(OIDOfBuiltin(B_INSTAT, pdp->atindex[0]));
  552.   }
  553.   if (c.kind == C_Variable &&
  554.       (!pdp->needsResultReg || isAppropriateRegister(c.v.data, brand))) {
  555.     /*
  556.      * We know the result variable.
  557.      */
  558.     result = c.v;
  559.     knowResult = TRUE;
  560.     /*
  561.      * abConNeedsAssigning = (c.v.abCon.kind == DD_Address);
  562.      * but this tickles a bug in the Sun 3.2 compiler.  It generates a tstl
  563.      * instead of a tstb .
  564.      */
  565.     if (c.v.abCon.kind == DD_Address) {
  566.       abConNeedsAssigning = TRUE;
  567.     } else {
  568.       abConNeedsAssigning = FALSE;
  569.     }
  570.   } else if (isExpression) {
  571.     knowResult = FALSE;
  572.     abConNeedsAssigning = FALSE;
  573.     assert(pdp->isFunction);
  574.     /* Try to reuse an existing temporary register as the answer */
  575.     if ((pdp->reuseTemp & ARG2) &&
  576.     (resultRegister = ddHasTempReg(arg2->data, brand)) >= 0) {
  577.       eraseTempIndication(&arg2->data, resultRegister);
  578.     } else if ((pdp->reuseTemp & ARG1) &&
  579.     (resultRegister = ddHasTempReg(arg1->data, brand)) >= 0) {
  580.       eraseTempIndication(&arg1->data, resultRegister);
  581.     } else if ((pdp->reuseTemp & SELF) &&
  582.     (resultRegister = ddHasTempReg(self->data, brand)) >= 0) {
  583.       eraseTempIndication(&self->data, resultRegister);
  584.     } else if (pdp->needsResultReg) {
  585.       resultRegister = forceAllocateReg(1, brand, nargs);
  586.     } else {
  587.       resultRegister = allocateReg(1, brand);
  588.     }
  589.     if (resultRegister != -1) {
  590.       result.data.kind = DD_Address;
  591.       result.data.value.address = nullAddress;
  592.       result.data.value.address.base = Register;
  593.       result.data.value.address.offset = resultRegister;
  594.       result.data.value.address.baseIsTemporary = TRUE;
  595.       result.abCon = buildConCon(INTEGERINDEX);
  596.     } else {
  597.       stackAddress = TS_Allocate(4, brand);
  598.       result.data.kind = DD_Address;
  599.       result.data.value.address = nullAddress;
  600.       result.data.value.address.base = regs_l;
  601.       result.data.value.address.baseIsTemporary = TRUE;
  602.       result.data.value.address.offset = stackAddress;
  603.       result.abCon = buildConCon(INTEGERINDEX);
  604.     }
  605.   } else {
  606.     result.data = nullDD;
  607.     result.abCon = nullDD;
  608.     knowResult = FALSE;
  609.     abConNeedsAssigning = FALSE;
  610.   }
  611.  
  612. /*
  613.  * The abcon needs to be assigned first, since it might be -(sp).
  614.  */
  615. #define SETRESULTABCON(S) if (!knowResult) result.abCon = (S); \
  616.     else if (abConNeedsAssigning) emitMove((S), result.abCon, 'l');
  617.  
  618.   TRACE2(primitive, 1, "Primitive %s of type %s", 
  619.     primOpName(typeIndex, opIndex), builtinTypeNames[typeIndex]);
  620.   switch (typeIndex) {
  621.     case ABSTRACTTYPEINDEX:
  622.       assert(FALSE);
  623.       break;
  624.     case ANYINDEX:
  625.       assert(FALSE);
  626.       break;
  627.     case ARRAYINDEX:
  628.       unimplementedPrimitive(opIndex, typeIndex);
  629.       break;
  630.     case BOOLEANINDEX:
  631.       anabcon = buildConCon(BOOLEANINDEX);
  632.       switch (opIndex) {
  633.     case 0: /* > */
  634.     case 1: /* >= */
  635.     case 2: /* < */
  636.     case 3: /* <= */
  637.     case 4: /* = */
  638.     case 5: /* != */
  639.       FREEV(&result);
  640.       result.abCon = anabcon;
  641.       vForceToTemp(arg1, TS_All);
  642.       vForceToTemp(self, TS_All);
  643.       result.data = generateCompare(self, arg1, 'l', unsignedCompareCs[opIndex]);
  644.       break;
  645.     case 6: /* & */
  646.       vForceToTemp(arg1, TS_All);
  647.       vForceToTemp(self, TS_All);
  648.       SETRESULTABCON(anabcon);
  649. #ifdef vax
  650.       emit("\textzv\t$0,");
  651.       writeDD(self->data, ',');
  652.       writeDD(arg1->data, ',');
  653.       writeDD(result.data, '\n');
  654. #endif
  655. #ifdef sun
  656.       prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
  657.       emit("\tandl\t");
  658.       writeDD(other->data, ',');
  659.       writeDD(tResult.data, '\n');
  660. #endif
  661.       break;
  662.     case 7: /* | */
  663.       vForceToTemp(arg1, TS_All);
  664.       vForceToTemp(self, TS_All);
  665.       SETRESULTABCON(anabcon);
  666. #ifdef vax
  667.       emit("\tbisl3\t");
  668.       writeDD(self->data, ',');
  669.       writeDD(arg1->data, ',');
  670.       writeDD(result.data, '\n');
  671. #endif
  672. #ifdef sun
  673.       prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
  674.       emit("\torl\t");
  675.       writeDD(other->data, ',');
  676.       writeDD(tResult.data, '\n');
  677. #endif
  678.       break;
  679.     case 8: /* ! */
  680.       if (self->data.kind == DD_PSLCondition) {
  681.         FREEV(&result);
  682.         result.data = self->data;
  683.         result.abCon = self->abCon;
  684.         result.data.value.condition.psl =
  685.           negatedConditions[(int)result.data.value.condition.psl];
  686.       } else {
  687.         vForceToTemp(self, TS_All);
  688.         SETRESULTABCON(anabcon);
  689.         if (c.kind == C_Variable) {
  690.           temp.data = buildManifestDD(1);
  691.           temp.abCon = buildConCon(INTEGERINDEX);
  692. #ifdef vax
  693.           emit("\tsubl3\t");
  694.           writeDD(self->data, ',');
  695.           writeDD(temp.data, ',');
  696.           writeDD(result.data, '\n');
  697. #endif
  698. #ifdef sun
  699.           prepareForSunOp(self, &temp, &result, FALSE, &other, &tResult);
  700.           emit("\tsubl\t");
  701.           writeDD(other->data, ',');
  702.           writeDD(tResult.data, '\n');
  703. #endif
  704.         } else if (c.kind == C_PSL || c.kind == C_Any) {
  705.           emit("\ttstl\t");
  706.           writeDD(self->data, '\n');
  707.           FREEV(&result);
  708.           result.data.kind = DD_PSLCondition;
  709.           result.data.value.condition.psl = EQL;
  710.           result.data.value.condition.isFloat = FALSE;
  711.           result.abCon = anabcon;
  712.         } else {
  713.           assert(FALSE);
  714.         }
  715.       }
  716.       break;
  717.     case 9: /* asString */
  718.       FREEV(&result);
  719.       moveDataToRegister(self, regs_arg1, DataBrand);
  720.       preemptReg(regs_scratch, 1);
  721.       preemptReg(regs_arg2, 2);
  722.       generateKernelCall("emboolean_asString");
  723.       FREEV(self);
  724.       claimReg(regs_arg1, 1, ODPBrand);
  725.       result.data = buildRegisterDD(regs_arg1);
  726.       result.abCon = buildConCon(STRINGINDEX);
  727.       break;
  728.     default:
  729.       unimplementedPrimitive(opIndex, typeIndex);
  730.       break;
  731.       }
  732.       break;
  733.     case CHARACTERINDEX:
  734.       anabcon = buildConCon(CHARACTERINDEX);
  735.       switch (opIndex) {
  736.     case 0: /* > */
  737.     case 1: /* >= */
  738.     case 2: /* < */
  739.     case 3: /* <= */
  740.     case 4: /* = */
  741.     case 5: /* != */
  742.       FREEV(&result);
  743.       result.abCon = buildConCon(BOOLEANINDEX);
  744.       vForceToTemp(arg1, TS_All);
  745.       vForceToTemp(self, TS_All);
  746.       result.data = generateCompare(self, arg1, 'l', unsignedCompareCs[opIndex]);
  747.       break;
  748.     case 6: /* asString */
  749.       FREEV(&result);
  750.       moveDataToRegister(self, regs_arg1, DataBrand);
  751.       preemptReg(regs_scratch, 1);
  752.       preemptReg(regs_arg2, 2);
  753.       generateKernelCall("emcharacter_asString");
  754.       FREEV(self);
  755.       claimReg(regs_arg1, 1, ODPBrand);
  756.       result.data = buildRegisterDD(regs_arg1);
  757.       result.abCon = buildConCon(STRINGINDEX);
  758.       break;
  759.     case 7: /* ord */
  760.       FREEV(&result);
  761.       result.data = self->data;
  762.       result.abCon = buildConCon(INTEGERINDEX);
  763.       DISCARDDD(self->data);
  764.       break;
  765.     case 8: /* Character.literal */
  766.       FREEV(&result);
  767.       FREEV(self);
  768.       result.data = arg1->data;
  769.       result.abCon = buildConCon(CHARACTERINDEX);
  770.       DISCARDDD(arg1->data);
  771.       break;
  772.     default:
  773.       unimplementedPrimitive(opIndex, typeIndex);
  774.       break;
  775.       }
  776.       break;
  777.     case CONDITIONINDEX:
  778.       switch (opIndex) {
  779.     case 0:    /* Create */
  780.       FREEV(&result);
  781.       result.data.kind = DD_Manifest;
  782.       result.data.value.manifest = 0;
  783.       result.abCon = buildConCon(CONDITIONINDEX);
  784.       break;
  785.     default:
  786.       unimplementedPrimitive(opIndex, typeIndex);
  787.       break;
  788.       }
  789.       break;
  790.     case INTEGERINDEX:
  791.       anabcon = buildConCon(INTEGERINDEX);
  792.       switch (opIndex) {
  793.     case 0: /* + */
  794.       vForceToTemp(arg1, TS_All);
  795.       vForceToTemp(self, TS_All);
  796.       SETRESULTABCON(anabcon);
  797. #ifdef vax
  798.       if (isSameDD(self->data, result.data)) {
  799.         do2OpAdd(self->data, arg1->data, 'l');
  800.         self->data = nullDD;
  801.       } else if (isSameDD(arg1->data, result.data)) {
  802.         do2OpAdd(arg1->data, self->data, 'l');
  803.         arg1->data = nullDD;
  804.       } else {
  805.         emit("\taddl3\t");
  806.         writeDD(self->data, ',');
  807.         writeDD(arg1->data, ',');
  808.         writeDD(result.data, '\n');
  809.       }
  810. #endif
  811. #ifdef sun
  812.       prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
  813.       emit("\tadd%sl\t",
  814.         other->data.kind == DD_Manifest && inRange(other->data.value.manifest, 1, 8) ? "q" : "");
  815.       writeDD(other->data, ',');
  816.       writeDD(tResult.data, '\n');
  817. #endif
  818.       break;
  819.     case 1: /* - */
  820.       vForceToTemp(arg1, TS_All);
  821.       vForceToTemp(self, TS_All);
  822.       SETRESULTABCON(anabcon);
  823.       if (arg1->data.kind == DD_Manifest && arg1->data.value.manifest == 0) {
  824.         FREEDD(result.data);
  825.         result.data = self->data;
  826.         self->data = nullDD;
  827. #ifdef vax
  828.       } else if (isSameDD(self->data, result.data)) {
  829.         if (arg1->data.kind == DD_Manifest && arg1->data.value.manifest == 1) {
  830.           emit("\tdecl\t");
  831.           writeDD(self->data, '\n');
  832.         } else if (arg1->data.kind == DD_Manifest && arg1->data.value.manifest == -1) {
  833.           emit("\tincl\t");
  834.           writeDD(self->data, '\n');
  835.         } else {
  836.           emit("\tsubl2\t");
  837.           writeDD(arg1->data, ',');
  838.           writeDD(self->data, '\n');
  839.         }
  840.       } else {
  841.         emit("\tsubl3\t");
  842.         writeDD(arg1->data, ',');
  843.         writeDD(self->data, ',');
  844.         writeDD(result.data, '\n');
  845. #endif
  846. #ifdef sun
  847.       } else {
  848.         prepareForSunOp(self, arg1, &result, FALSE, &other, &tResult);
  849.         emit("\tsub%sl\t",
  850.           other->data.kind == DD_Manifest && inRange(other->data.value.manifest, 1, 8) ? "q" : "");
  851.         writeDD(other->data, ',');
  852.         writeDD(tResult.data, '\n');
  853. #endif
  854.  
  855.       }
  856.       break;
  857.     case 2: /* * */
  858.       vForceToTemp(arg1, TS_All);
  859.       vForceToTemp(self, TS_All);
  860. #ifdef sun
  861.       assert(isDataRegister(result.data));
  862. #endif
  863.       SETRESULTABCON(anabcon);
  864. #ifdef vax
  865.       emit("\tmull3\t");
  866.       writeDD(self->data, ',');
  867.       writeDD(arg1->data, ',');
  868.       writeDD(result.data, '\n');
  869. #endif
  870. #ifdef sun
  871.       prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
  872.       emit("\tmulsl\t");
  873.       writeDD(other->data, ',');
  874.       writeDD(tResult.data, '\n');
  875. #endif
  876.       break;
  877.     case 3: /* / */
  878.       vForceToTemp(arg1, TS_All);
  879.       vForceToTemp(self, TS_All);
  880. #ifdef sun
  881.       assert(isDataRegister(result.data));
  882. #endif
  883.       SETRESULTABCON(anabcon);
  884. #ifdef vax
  885.       emit("\tdivl3\t");
  886.       writeDD(arg1->data, ',');
  887.       writeDD(self->data, ',');
  888.       writeDD(result.data, '\n');
  889. #endif
  890. #ifdef sun
  891.       prepareForSunOp(self, arg1, &result, FALSE, &other, &tResult);
  892.       emit("\tdivsl\t");
  893.       writeDD(other->data, ',');
  894.       writeDD(tResult.data, '\n');
  895. #endif
  896.       break;
  897.     case 4: /* # */
  898.       vForceToTemp(arg1, TS_All);
  899.       vForceToTemp(self, TS_All);
  900. #ifdef sun
  901.       assert(isDataRegister(result.data));
  902. #endif
  903.       SETRESULTABCON(anabcon);
  904. #ifdef vax
  905.       scratch = getScratch(DataBrand, 2);
  906.       emit("\tdivl3\t");
  907.       writeDD(arg1->data, ',');
  908.       writeDD(self->data, ',');
  909.       writeDD(scratch, '\n');
  910.       emit("\tmull2\t");
  911.       writeDD(arg1->data, ',');
  912.       writeDD(scratch, '\n');
  913.       emit("\tsubl3\t");
  914.       writeDD(scratch, ',');
  915.       writeDD(self->data, ',');
  916.       writeDD(result.data, '\n');
  917.       freeScratch(scratch);
  918. #endif
  919. #ifdef sun
  920.       needsFreeing = FALSE;
  921.       tempReg = ddHasTempReg(arg1->data, DataBrand);
  922.       if (tempReg < 0) {
  923.         tempReg = forceAllocateReg(1, DataBrand, 2);
  924.         needsFreeing = TRUE;
  925.       }
  926.       temp.data = buildRegisterDD(tempReg);
  927.       temp.abCon = buildConCon(INTEGERINDEX);
  928.       prepareForSunOp(self, arg1, &temp, FALSE, &other, &tResult);
  929.       emit("\tdivsll\t");
  930.       writeDD(other->data, ',');
  931.       writeDD(result.data, ':');
  932.       writeDD(temp.data, '\n');
  933.       if (needsFreeing) FREEV(&temp);
  934. #endif
  935.       break;
  936.     case 5: /* > */
  937.     case 6: /* >= */
  938.     case 7: /* < */
  939.     case 8: /* <= */
  940.     case 9: /* = */
  941.     case 10: /* != */
  942.       FREEV(&result);
  943.       result.abCon = buildConCon(BOOLEANINDEX);
  944.       vForceToTemp(arg1, TS_All);
  945.       vForceToTemp(self, TS_All);
  946.       result.data = generateCompare(self, arg1, 'l', compareCs[opIndex - 5]);
  947.       break;
  948.     case 11: /* asString */
  949.       FREEV(&result);
  950.       moveDataToRegister(self, regs_arg1, DataBrand);
  951.       preemptReg(regs_scratch, 1);
  952.       preemptReg(regs_arg2, 2);
  953.       generateKernelCall("eminteger_asString");
  954.       FREEV(self);
  955.       claimReg(regs_arg1, 1, ODPBrand);
  956.       result.data = buildRegisterDD(regs_arg1);
  957.       result.abCon = buildConCon(STRINGINDEX);
  958.       break;
  959.     case 12: /* ~ */
  960.       vForceToTemp(self, TS_All);
  961.       SETRESULTABCON(anabcon);
  962. #ifdef vax
  963.       emit("\tmnegl\t");
  964.       writeDD(self->data, ',');
  965.       writeDD(result.data, '\n');
  966. #endif
  967. #ifdef sun
  968.       prepareForSunOp(self, self, &result, FALSE, &other, &tResult);
  969.       emit("\tnegl\t");
  970.       writeDD(tResult.data, '\n');
  971. #endif
  972.       break;
  973.     case 13: /* asReal */
  974.       vForceToTemp(self, TS_All);
  975.       SETRESULTABCON(buildConCon(REALINDEX));
  976. #ifdef vax
  977.       emit("\tcvtlf\t");
  978.       writeDD(self->data, ',');
  979.       writeDD(result.data, '\n');
  980. #endif
  981. #ifdef sun
  982.       if (isAddressRegister(self->data)) {
  983.         tempReg = forceAllocateReg(1, DataBrand, 1);
  984.         temp.data = buildRegisterDD(tempReg);
  985.         emitMove(self->data, temp.data, 'l');
  986.         FREEDD(self->data);
  987.         self->data = temp.data;
  988.       }
  989.       emit("\tfmovel\t");
  990.       writeDD(self->data, ',');
  991.       emit("fp0\n\tfmoves\tfp0,");
  992.       writeDD(result.data, '\n');
  993. #endif
  994.       break;
  995.     default:
  996.       unimplementedPrimitive(opIndex, typeIndex);
  997.       break;
  998.       }
  999.       break;
  1000.     case NILINDEX:
  1001.       assert(FALSE);
  1002.       break;
  1003.     case NODEINDEX:
  1004.       switch (opIndex) {
  1005.     case 0: /* delay */
  1006.       moveDataToRegister(arg1, regs_arg1, ODPBrand);
  1007.       preemptReg(regs_scratch, 1);
  1008.       preemptReg(regs_arg2, 2);
  1009.       generateKernelCall("em_delay");
  1010.       break;
  1011.     case 1: /* waitUntil */
  1012.       moveDataToRegister(arg1, regs_arg1, ODPBrand);
  1013.       preemptReg(regs_scratch, 1);
  1014.       preemptReg(regs_arg2, 2);
  1015.       generateKernelCall("em_waitUntil");
  1016.       break;
  1017.     case 2: /* getActiveNodes */
  1018.     case 3: /* getAllNodes */
  1019.       preemptReg(regs_scratch, 4);
  1020.       if (opIndex == 2) generateKernelCall("em_getActiveNodes");
  1021.       else generateKernelCall("em_getAllNodes");
  1022.       claimReg(regs_arg1, 2, VariableBrand);
  1023.       FREEV(&result);
  1024.       result.data = buildRegisterDD(regs_arg1);
  1025.       result.abCon = nextAddress(result.data);
  1026.       setDDAbstractType(result.abCon, OIDOfBuiltin(B_INSTAT, NODELISTINDEX));
  1027.       break;
  1028.     case 4: /* getNodeInformation */
  1029.       moveDataToRegister(arg1, regs_arg1, ODPBrand);
  1030.       preemptReg(regs_scratch, 1);
  1031.       preemptReg(regs_arg2, 2);
  1032.       generateKernelCall("em_getNodeInformation");
  1033.       FREEV(arg1);
  1034.       claimReg(regs_arg1, 2, VariableBrand);
  1035.       FREEV(&result);
  1036.       result.data = buildRegisterDD(regs_arg1);
  1037.       result.abCon = nextAddress(result.data);
  1038.       setDDAbstractType(result.abCon, OIDOfBuiltin(B_INSTAT, NODELISTELEMENTINDEX));
  1039.       break;
  1040.     case 5: /* setNodeEventHandler */
  1041.     case 6: /* removeNodeEventHandler */
  1042.       moveVariableToRegisters(arg1, regs_arg1);
  1043.       preemptReg(regs_scratch, 1);
  1044.       preemptReg(regs_arg3, 1);
  1045.       if (opIndex == 5) generateKernelCall("em_setNodeEventHandler");
  1046.       else generateKernelCall("em_removeNodeEventHandler");
  1047.       break;
  1048.     case 7: /* getStdin */
  1049.     case 8: /* getStdout */
  1050.     case 9: /* getName */
  1051.     case 20: /* getStdin  on NODE */
  1052.     case 21: /* getStdout on NODE */
  1053.       FREEV(&result);
  1054.       preemptReg(regs_scratch, 4);
  1055.       if (opIndex == 7) generateKernelCall("em_getStdIn");
  1056.       else if (opIndex == 8) generateKernelCall("em_getStdOut");
  1057.       else if (opIndex == 9) generateKernelCall("em_getName");
  1058.       else if (opIndex == 20) generateKernelCall("em_getMyStdIn");
  1059.       else if (opIndex == 21) generateKernelCall("em_getMyStdOut");
  1060.       else assert(FALSE);
  1061.       claimReg(regs_arg1, 1, ODPBrand);
  1062.       result.data = buildRegisterDD(regs_arg1);
  1063.       if (opIndex == 7 || opIndex == 20) {
  1064.         result.abCon = buildConCon(INSTREAMINDEX);
  1065.       } else if (opIndex == 8) {
  1066.         result.abCon = buildConCon(STRINGINDEX);
  1067.       } else {
  1068.         result.abCon = buildConCon(OUTSTREAMINDEX);
  1069.       }
  1070.       break;
  1071.     case 30:
  1072.       moveDataToRegister(arg1, regs_arg1);
  1073.       preemptReg(regs_scratch, 1);
  1074.       preemptReg(regs_arg2, 2);
  1075.       generateKernelCall("emx_nextevent");
  1076.       break;
  1077.     default:
  1078.       unimplementedPrimitive(opIndex, typeIndex);
  1079.       break;
  1080.       }
  1081.       break;
  1082.     case SIGNATUREINDEX:
  1083.       unimplementedPrimitive(opIndex, typeIndex);
  1084.       break;
  1085.     case REALINDEX:
  1086.       anabcon = buildConCon(REALINDEX);
  1087.       switch (opIndex) {
  1088.     case 0: /* + */
  1089.       vForceToTemp(arg1, TS_All);
  1090.       vForceToTemp(self, TS_All);
  1091.       SETRESULTABCON(buildConCon(REALINDEX));
  1092. #ifdef vax
  1093.       if (isSameDD(self->data, result.data)) {
  1094.         do2OpAdd(self->data, arg1->data, 'f');
  1095.         self->data = nullDD;
  1096.       } else if (isSameDD(arg1->data, result.data)) {
  1097.         do2OpAdd(arg1->data, self->data, 'f');
  1098.         arg1->data = nullDD;
  1099.       } else {
  1100.         emit("\taddf3\t");
  1101.         writeDD(self->data, ',');
  1102.         writeDD(arg1->data, ',');
  1103.         writeDD(result.data, '\n');
  1104.       }
  1105. #endif
  1106. #ifdef sun
  1107.       doSunRealOp(self->data, arg1->data, "add", result.data);
  1108. #endif
  1109.       break;
  1110.     case 1: /* - */
  1111.       vForceToTemp(arg1, TS_All);
  1112.       vForceToTemp(self, TS_All);
  1113.       SETRESULTABCON(buildConCon(REALINDEX));
  1114. #ifdef vax
  1115.       if (arg1->data.kind == DD_RealManifest &&
  1116.           atof(arg1->data.value.realmanifest) == 0.0) {
  1117.         FREEDD(result.data);
  1118.         result.data = self->data;
  1119.         self->data = nullDD;
  1120.       } else if (isSameDD(self->data, result.data)) {
  1121.         emit("\tsubf2\t");
  1122.         writeDD(arg1->data, ',');
  1123.         writeDD(self->data, '\n');
  1124.       } else {
  1125.         emit("\tsubf3\t");
  1126.         writeDD(arg1->data, ',');
  1127.         writeDD(self->data, ',');
  1128.         writeDD(result.data, '\n');
  1129.       }
  1130. #endif
  1131. #ifdef sun
  1132.       doSunRealOp(self->data, arg1->data, "sub", result.data);
  1133. #endif
  1134.       break;
  1135.     case 2: /* * */
  1136.       vForceToTemp(arg1, TS_All);
  1137.       vForceToTemp(self, TS_All);
  1138.       SETRESULTABCON(buildConCon(REALINDEX));
  1139. #ifdef vax
  1140.       if (isSameDD(self->data, result.data)) {
  1141.         emit("\tmulf2\t");
  1142.         writeDD(arg1->data, ',');
  1143.         writeDD(result.data, '\n');
  1144.       } else if (isSameDD(arg1->data, result.data)) {
  1145.         emit("\tmulf2\t");
  1146.         writeDD(self->data, ',');
  1147.         writeDD(result.data, '\n');
  1148.       } else {
  1149.         emit("\tmulf3\t");
  1150.         writeDD(self->data, ',');
  1151.         writeDD(arg1->data, ',');
  1152.         writeDD(result.data, '\n');
  1153.       }
  1154. #endif
  1155. #ifdef sun
  1156.       doSunRealOp(self->data, arg1->data, "mul", result.data);
  1157. #endif
  1158.       break;
  1159.     case 3: /* / */
  1160.       vForceToTemp(arg1, TS_All);
  1161.       vForceToTemp(self, TS_All);
  1162.       SETRESULTABCON(buildConCon(REALINDEX));
  1163. #ifdef vax
  1164.       if (isSameDD(self->data, result.data)) {
  1165.         emit("\tdivf2\t");
  1166.         writeDD(arg1->data, ',');
  1167.         writeDD(self->data, '\n');
  1168.       } else {
  1169.         emit("\tdivf3\t");
  1170.         writeDD(arg1->data, ',');
  1171.         writeDD(self->data, ',');
  1172.         writeDD(result.data, '\n');
  1173.       }
  1174. #endif
  1175. #ifdef sun
  1176.       doSunRealOp(self->data, arg1->data, "div", result.data);
  1177. #endif
  1178.       break;
  1179.     case 4: /* # */
  1180.       FREEV(&result);
  1181.       result.data = nilDD;
  1182.       result.abCon = nilDD;
  1183.       generateKernelCall("em_assertionFailure");
  1184.       break;
  1185.     case 5: /* > */
  1186.     case 6: /* >= */
  1187.     case 7: /* < */
  1188.     case 8: /* <= */
  1189.     case 9: /* = */
  1190.     case 10: /* != */
  1191.       FREEV(&result);
  1192.       result.abCon = buildConCon(BOOLEANINDEX);
  1193.       vForceToTemp(arg1, TS_All);
  1194.       vForceToTemp(self, TS_All);
  1195.       result.data = generateCompare(self, arg1, 'f', compareCs[opIndex - 5]);
  1196.       break;
  1197.     case 11: /* asString */
  1198.       FREEV(&result);
  1199.       moveDataToRegister(self, regs_arg1, DataBrand);
  1200.       preemptReg(regs_scratch, 1);
  1201.       preemptReg(regs_arg2, 2);
  1202.       generateKernelCall("emreal_asString");
  1203.       FREEV(self);
  1204.       claimReg(regs_arg1, 1, ODPBrand);
  1205.       result.data = buildRegisterDD(regs_arg1);
  1206.       result.abCon = buildConCon(STRINGINDEX);
  1207.       break;
  1208.     case 12: /* asInteger */
  1209.       vForceToTemp(self, TS_All);
  1210.       SETRESULTABCON(buildConCon(INTEGERINDEX));
  1211. #ifdef vax
  1212.       emit("\tcvtrfl\t");
  1213.       writeDD(self->data, ',');
  1214.       writeDD(result.data, '\n');
  1215. #endif
  1216. #ifdef sun
  1217.       if (isAddressRegister(self->data)) {
  1218.         temp.data = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
  1219.         emitMove(self->data, temp.data, 'l');
  1220.         FREEDD(self->data);
  1221.         self->data = temp.data;
  1222.       }
  1223.       emit("\tfintrzs\t");
  1224.       writeDD(self->data, ',');
  1225.       emit("fp0\n\tfmovel\tfp0,");
  1226.       writeDD(result.data, '\n');
  1227. #endif
  1228.       break;
  1229.     case 13: /* ~ */
  1230.       vForceToTemp(self, TS_All);
  1231.       SETRESULTABCON(anabcon);
  1232. #ifdef vax
  1233.       emit("\tmnegf\t");
  1234.       writeDD(self->data, ',');
  1235.       writeDD(result.data, '\n');
  1236. #endif
  1237. #ifdef sun
  1238.       assert(isDataRegister(result.data));
  1239.       emitMove(self->data, result.data, 'l');
  1240.       emit("\tbchg\t");
  1241.       writeDD(buildManifestDD(31), ',');
  1242.       writeDD(result.data, '\n');
  1243. #endif
  1244.       break;
  1245.     default:
  1246.       unimplementedPrimitive(opIndex, typeIndex);
  1247.       break;
  1248.       }
  1249.       break;
  1250.     case STRINGINDEX:
  1251.       switch (opIndex) {
  1252.     case 0: /* getElement */
  1253.       self = forceIntoRegister(self, ODPBrand);
  1254.       arg1 = forceIntoRegister(arg1, DataBrand);
  1255.       SETRESULTABCON(buildConCon(CHARACTERINDEX));
  1256.       checkRange(self, arg1, TRUE, String_sizeInBytes);
  1257. #ifdef vax
  1258.       emit("\tmovzbl\t%d(%s)[%s],", String_data,
  1259.         RN(self->data.value.address.offset), RN(arg1->data.value.address.offset));
  1260.       writeDD(result.data, '\n');
  1261. #endif
  1262. #ifdef sun
  1263.       temp.data = buildManifestDD(0);
  1264.       temp.abCon = buildConCon(INTEGERINDEX);
  1265.       prepareForSunOp(&temp, &temp, &result, FALSE, &other, &tResult);
  1266.       if (isMemory(tResult.data)) {
  1267.         tResult.data.value.address.offset += 3;
  1268.       }
  1269.       emit("\tmovb\t");
  1270.       emit("%s@(%d,%s:l),", RN(self->data.value.address.offset), String_data,
  1271.         RN(arg1->data.value.address.offset));
  1272.       writeDD(tResult.data, '\n');
  1273. #endif
  1274.       break;
  1275.     case 11: /* lowlevelsleazysetElement */
  1276.       self = forceIntoRegister(self, ODPBrand);
  1277.       arg1 = forceIntoRegister(arg1, DataBrand);
  1278. /*      checkRange(self, arg1, TRUE, String_sizeInBytes); */
  1279. #ifdef vax
  1280.       emit("\tcvtlb\t");
  1281.       writeDD(arg2->data, ',');
  1282.       emit("%d(%s)[%s]\n", String_data,
  1283.         RN(self->data.value.address.offset),
  1284.         RN(arg1->data.value.address.offset));
  1285. #endif
  1286. #ifdef sun
  1287.       if (isMemory(arg2->data)) vForceToTemp(arg2, TS_Stack);
  1288.       if (isMemory(arg2->data)) {
  1289.         arg2->data.value.address.offset += 3;
  1290.       }
  1291.       emit("\tmovb\t");
  1292.       writeDD(arg2->data, ',');
  1293.       emit("%s@(%d,%s:l)\n", RN(self->data.value.address.offset),
  1294.         String_data,
  1295.         RN(arg1->data.value.address.offset));
  1296. #endif
  1297.       break;
  1298.     case 1: /* getSlice */
  1299.       FREEV(&result);
  1300.       moveDataToRegister(arg2, regs_arg3, DataBrand);
  1301.       moveDataToRegister(arg1, regs_arg2, DataBrand);
  1302.       moveDataToRegister(self, regs_arg1, ODPBrand);
  1303.  
  1304.       preemptReg(regs_scratch, 1);
  1305.  
  1306.       generateKernelCall("ems_getSlice");
  1307.       FREEV(arg2);
  1308.       FREEV(arg1);
  1309.       FREEV(self);
  1310.       claimReg(regs_arg1, 1, ODPBrand);
  1311.       result.data = buildRegisterDD(regs_arg1);
  1312.       result.abCon = buildConCon(STRINGINDEX);
  1313.       break;
  1314.     case 2: /* || */
  1315.       FREEV(&result);
  1316.       moveDataToRegister(arg1, regs_arg2, ODPBrand);
  1317.       moveDataToRegister(self, regs_arg1, ODPBrand);
  1318.  
  1319.       preemptReg(regs_scratch, 1);
  1320.       preemptReg(regs_arg3, 1);
  1321.  
  1322.       generateKernelCall("ems_catenate");
  1323.       FREEV(arg1);
  1324.       FREEV(self);
  1325.  
  1326.       claimReg(regs_arg1, 1, ODPBrand);
  1327.       result.data = buildRegisterDD(regs_arg1);
  1328.       result.abCon = buildConCon(STRINGINDEX);
  1329.       break;
  1330.     case 3: /* asString */
  1331.       FREEV(&result);
  1332.       result.data = self->data;
  1333.       result.abCon = self->abCon;
  1334.       break;
  1335.     case 4: /* > */
  1336.     case 5: /* >= */
  1337.     case 6: /* < */
  1338.     case 7: /* <= */
  1339.     case 8: /* = */
  1340.     case 9: /* != */
  1341. #ifdef vax
  1342.       FREEV(&result);
  1343.       arg1 = forceIntoRegister(arg1, ODPBrand);
  1344.       self = forceIntoRegister(self, ODPBrand);
  1345.  
  1346.       emit("\tcmpc5\t%d(%s), %d(%s), $0, ",
  1347.         String_sizeInBytes, RN(self->data.value.address.offset),
  1348.         String_data, RN(self->data.value.address.offset));
  1349.       emit("%d(%s), %d(%s)\n",
  1350.         String_sizeInBytes, RN(arg1->data.value.address.offset),
  1351.         String_data, RN(arg1->data.value.address.offset));
  1352.       FREEV(self);
  1353.       FREEV(arg1);
  1354.       result.data.kind = DD_PSLCondition;
  1355.       result.data.value.condition.psl = unsignedCompareCs[opIndex - 4];
  1356.       result.data.value.condition.isFloat = FALSE;
  1357.       result.abCon = buildConCon(BOOLEANINDEX);
  1358. #endif
  1359. #ifdef sun
  1360.       FREEV(&result);
  1361.       moveDataToRegister(arg1, regs_arg2, ODPBrand);
  1362.       moveDataToRegister(self, regs_arg1, ODPBrand);
  1363.       preemptReg(regs_scratch, 1);
  1364.       preemptReg(regs_arg3, 1);
  1365.       generateKernelCall("ems_compare");
  1366.       FREEV(arg1);
  1367.       FREEV(self);
  1368.       result.data.kind = DD_PSLCondition;
  1369.       result.data.value.condition.psl = unsignedCompareCs[opIndex - 4];
  1370.       result.data.value.condition.isFloat = FALSE;
  1371.       result.abCon = buildConCon(BOOLEANINDEX);
  1372. #endif
  1373.       break;
  1374.     case 10: /* length */
  1375.       FREEV(&result);
  1376.       result = *forceIntoRegister(self, ODPBrand);
  1377.       DISCARDV(self);
  1378.       result.abCon = buildConCon(INTEGERINDEX);
  1379.       result.data = increaseIndirection(result.data);
  1380.       result.data.value.address.offset = String_sizeInBytes;
  1381.       break;
  1382.     default:
  1383.       unimplementedPrimitive(opIndex, typeIndex);
  1384.       break;
  1385.       }
  1386.       break;
  1387.     case VECTORINDEX:
  1388.       /*
  1389.        * Vectors need to know if they are holding 32 bit data pointers with
  1390.        * known abcons or 64 bit data pointer/abcon pairs.  This is found by
  1391.        * the following stuff:
  1392.        *     1.  Look at the abcon for self.  fetch the concrete oblit.
  1393.        *     2.  Find the getelement operation, and fetch its result symbol
  1394.        *     3.  Look at its types.
  1395.        * This process implies that when we do vector.of[X], we need to change
  1396.        * X depending on the know concrete type status of the setelement
  1397.        * calls.  For the moment, lets just worry about the builtin guys.
  1398.        */
  1399.       assert (self->abCon.kind != DD_AbCon ||
  1400.     getConcreteTypeFromAbCon(self->abCon) == theObject);
  1401.       ct = theObject;
  1402.       elementTypeSymbol = getElementTypeSymbol(ct);
  1403.       elementTypeSize = getSymbolSize(elementTypeSymbol);
  1404.       switch (opIndex) {
  1405.     case 0: /* getElement */
  1406.       arg1 = forceIntoRegister(arg1, DataBrand);
  1407.       elementv = forceIntoRegister(self, ODPBrand);
  1408.       element = elementv->data;
  1409.       if (! knowResult) {
  1410.         if (elementTypeSize <= 4) {
  1411.           FREEV(&result);
  1412.           result.abCon = vGetSymbolAbCon(elementTypeSymbol, nullDD);
  1413.           assert(result.abCon.kind == DD_AbCon);
  1414.           brand = oidToBrand(getDDAbstractType(result.abCon));
  1415.           resultRegister = allocateReg(1, brand);
  1416.           if (resultRegister != -1) {
  1417.         result.data.kind = DD_Address;
  1418.         result.data.value.address = nullAddress;
  1419.         result.data.value.address.base = Register;
  1420.         result.data.value.address.offset = resultRegister;
  1421.         result.data.value.address.baseIsTemporary = TRUE;
  1422.           } else {
  1423.         stackAddress = TS_Allocate(4, brand);
  1424.         result.data.kind = DD_Address;
  1425.         result.data.value.address = nullAddress;
  1426.         result.data.value.address.base = regs_l;
  1427.         result.data.value.address.baseIsTemporary = TRUE;
  1428.         result.data.value.address.offset = stackAddress;
  1429.           }
  1430.         } else {
  1431.           assert(elementTypeSize == 8);
  1432.           FREEV(&result);
  1433.           stackAddress = TS_Allocate(8, VariableBrand);
  1434.           result.data.value.address.base = regs_l;
  1435.           result.data.value.address.baseIsTemporary = TRUE;
  1436.           result.data.value.address.offset = stackAddress;
  1437.           result.abCon = nextAddress(result.data);
  1438.           result.abCon.value.address.baseIsTemporary = TRUE;
  1439.           setDDAbstractType(result.abCon, getDDAbstractType(c.v.abCon));
  1440.         }
  1441.       }
  1442.       checkRange(elementv, arg1, FALSE,
  1443.         (ct->b.oblit.f.immutable ? IMVector_sizeInBytes : Vector_sizeInBytes) - 4);
  1444.       element = increaseIndirection(element);
  1445.       element.value.address.offset = 
  1446.         ct->b.oblit.f.immutable ? IMVector_data : Vector_data;
  1447.       element.value.address.hasIndex = TRUE;
  1448.       element.value.address.indexReg = arg1->data.value.address.offset;
  1449.       elementAbCon = vGetSymbolAbCon(elementTypeSymbol, element);
  1450.       indexSize = elementTypeSize;
  1451.       if (elementTypeSize == 1) {
  1452. #ifdef vax
  1453.         emit("\tmovzbl\t");
  1454.         writeDD(element, ',');
  1455.         writeDD(result.data, '\n');
  1456. #endif
  1457. #ifdef sun
  1458.         temp.data = buildManifestDD(0);
  1459.         temp.abCon = buildConCon(INTEGERINDEX);
  1460.         prepareForSunOp(&temp, &temp, &result, FALSE, &other, &tResult);
  1461.         if (isMemory(tResult.data)) {
  1462.           tResult.data.value.address.offset += 3;
  1463.         }
  1464.         emitMove(element, tResult.data, 'b');
  1465. #endif
  1466.         FREEDD(element);
  1467.         FREEDD(elementAbCon);
  1468.       } else {
  1469.         ddGenerateAssign(result.data, result.abCon, element, elementAbCon);
  1470.       }
  1471.       FREEV(arg1);
  1472.       assert(self == elementv);
  1473.       DISCARDV(self);
  1474.       if (elementTypeSize == 8) {
  1475.         if (result.data.kind == DD_Address &&
  1476.         result.data.value.address.autoDecrement) {
  1477.           /* we are pushing this on the stack */
  1478.           assert(result.abCon.kind == DD_Address);
  1479.           assert(result.abCon.value.address.autoDecrement);
  1480.           /* no need to fix the Ab/Con = what we stored will be fine */
  1481.         } else {
  1482.           fixDDView(result.abCon, result.abCon,
  1483.         getDDAbstractType(result.abCon), FALSE);
  1484.         }
  1485.       }
  1486.       break;
  1487.     case 1: /* setElement */
  1488.       if (arg2->data.kind == DD_Address && arg2->data.value.address.autoIncrement &&
  1489.           (arg1->data.kind == DD_Address && arg1->data.value.address.autoIncrement ||
  1490.            self->data.kind == DD_Address && self->data.value.address.autoIncrement)) {
  1491.         implementationBug("Can't do set elements of hairy expressions.");
  1492.         return;
  1493.       }
  1494.       self = forceIntoRegister(self, ODPBrand);
  1495.       element = self->data;
  1496.       arg1 = forceIntoRegister(arg1, DataBrand);
  1497.       checkRange(self, arg1, FALSE,
  1498.         (ct->b.oblit.f.immutable ? IMVector_sizeInBytes : Vector_sizeInBytes) - 4);
  1499.       element = increaseIndirection(element);
  1500.       element.value.address.offset = 
  1501.         ct->b.oblit.f.immutable ? IMVector_data : Vector_data;
  1502.       element.value.address.hasIndex = TRUE;
  1503.       element.value.address.indexReg = arg1->data.value.address.offset;
  1504.       elementAbCon = vGetSymbolAbCon(elementTypeSymbol, element);
  1505.       setDDAbstractType(elementAbCon, getDDAbstractType(arg2->abCon));
  1506.       indexSize = elementTypeSize;
  1507.       if (elementTypeSize == 1) {
  1508. #ifdef sun
  1509.         temp = *arg2;
  1510.         if (isMemory(temp.data)) {
  1511.           temp.data.value.address.offset += 3;
  1512.         }
  1513.         emitMove(temp.data, element, 'b');
  1514. #endif
  1515. #ifdef vax
  1516.         emit("\tcvtlb\t");
  1517.         writeDD(arg2->data, ',');
  1518.         writeDD(element, '\n');
  1519. #endif
  1520.       } else {
  1521.         if (arg2->data.kind == DD_Address &&
  1522.         arg2->data.value.address.autoIncrement &&
  1523.         arg2->abCon.kind == DD_Address &&
  1524.         arg2->abCon.value.address.autoIncrement) {
  1525.           /* panic.  we need to fix the ab-con, but cannot do it now. */
  1526.           OID realOID;
  1527.           realOID = getDDAbstractType(elementAbCon);
  1528.           setDDAbstractType(elementAbCon, (OID) 0);
  1529.           ddGenerateMovqAssign(elementTypeSize, element, elementAbCon,
  1530.         arg2->data, arg2->abCon);
  1531.           DISCARDV(arg2);
  1532.           setDDAbstractType(elementAbCon, realOID);
  1533.         } else {
  1534.           ddGenerateMovqAssign(elementTypeSize, element, elementAbCon,
  1535.         arg2->data, arg2->abCon);
  1536.           DISCARDV(arg2);
  1537.         }
  1538.       }
  1539.       break;
  1540.     case 2: /* upb */
  1541.       self = forceIntoRegister(self, ODPBrand);
  1542.       self->data = increaseIndirection(self->data);
  1543.       self->data.value.address.offset = 
  1544.         (ct->b.oblit.f.immutable ? IMVector_sizeInBytes : Vector_sizeInBytes) - 4;
  1545.       SETRESULTABCON(buildConCon(INTEGERINDEX));
  1546.       emitMove(self->data, result.data, 'l');
  1547.       break;
  1548.     case 3: /* lwb */
  1549.       FREEV(&result);
  1550.       result.data.kind = DD_Manifest;
  1551.       result.data.value.manifest = 0;
  1552.       result.abCon = buildConCon(INTEGERINDEX);
  1553.       break;
  1554.     case 4: /* getSlice */
  1555.       FREEV(&result);
  1556.       assert(self->abCon.kind == DD_AbCon);
  1557.       result.abCon = self->abCon;
  1558.       moveDataToRegister(arg2, regs_arg3, DataBrand);
  1559.       moveDataToRegister(arg1, regs_arg2, DataBrand);
  1560.       moveDataToRegister(self, regs_arg1, ODPBrand);
  1561.       preemptReg(regs_scratch, 1);
  1562.       if (elementTypeSize == 1) {
  1563.         generateKernelCall("emvector_get1Slice");
  1564.       } else if (elementTypeSize == 4) {
  1565.         generateKernelCall("emvector_get4Slice");
  1566.       } else {
  1567.         assert(elementTypeSize == 8);
  1568.         generateKernelCall("emvector_get8Slice");
  1569.       }
  1570.       FREEV(arg2);
  1571.       FREEV(arg1);
  1572.       FREEV(self);
  1573.       claimReg(regs_arg1, 1, ODPBrand);
  1574.       result.data = buildRegisterDD(regs_arg1);
  1575.       break;
  1576.     case 5: /* setSlice */
  1577.       FREEV(&result);
  1578.       moveDataToRegister(arg3, regs_scratch, ODPBrand);
  1579.       moveDataToRegister(arg2, regs_arg3, DataBrand);
  1580.       moveDataToRegister(arg1, regs_arg2, DataBrand);
  1581.       moveDataToRegister(self, regs_arg1, ODPBrand);
  1582.       if (elementTypeSize == 1) {
  1583.         generateKernelCall("emvector_set1Slice");
  1584.       } else if (elementTypeSize == 4) {
  1585.         generateKernelCall("emvector_set4Slice");
  1586.       } else {
  1587.         assert(elementTypeSize == 8);
  1588.         generateKernelCall("emvector_set8Slice");
  1589.       }
  1590.       FREEV(arg3);
  1591.       FREEV(arg2);
  1592.       FREEV(arg1);
  1593.       FREEV(self);
  1594.       break;
  1595.     case 6: /* catenate */
  1596.       FREEV(&result);
  1597.       assert(self->abCon.kind == DD_AbCon);
  1598.       result.abCon = self->abCon;
  1599.       moveDataToRegister(arg1, regs_arg2, ODPBrand);
  1600.       moveDataToRegister(self, regs_arg1, ODPBrand);
  1601.  
  1602.       preemptReg(regs_scratch, 1);
  1603.       preemptReg(regs_arg3, 1);
  1604.  
  1605.       if (elementTypeSize == 1) {
  1606.         generateKernelCall("emvector_catenate1");
  1607.       } else if (elementTypeSize == 4) {
  1608.         generateKernelCall("emvector_catenate4");
  1609.       } else {
  1610.         assert(elementTypeSize == 8);
  1611.         generateKernelCall("emvector_catenate8");
  1612.       }
  1613.       FREEV(arg1);
  1614.       FREEV(self);
  1615.  
  1616.       claimReg(regs_arg1, 1, ODPBrand);
  1617.       result.data = buildRegisterDD(regs_arg1);
  1618.       break;
  1619.     default:
  1620.       unimplementedPrimitive(opIndex, typeIndex);
  1621.       }
  1622.       break;
  1623.     case TIMEINDEX:
  1624.       anabcon = buildConCon(TIMEINDEX);
  1625.       if (opIndex < 0) {
  1626.     unimplementedPrimitive(opIndex, typeIndex);
  1627.       } else if (opIndex <= 9) {
  1628.     FREEV(&result);
  1629.     result.abCon = buildConCon(TIMEINDEX);
  1630.     moveDataToRegister(arg1, regs_arg2, ODPBrand);
  1631.     moveDataToRegister(self, regs_arg1, ODPBrand);
  1632.     preemptReg(regs_scratch, 1);
  1633.     preemptReg(regs_arg3, 1);
  1634.     FREEV(self);
  1635.     if (opIndex <= 3) {
  1636.       sprintf(buffer, "emtime_%s", timeOpNames[opIndex]);
  1637.       generateKernelCall(buffer);
  1638.       claimReg(regs_arg1, 1, ODPBrand);
  1639.       result.data = buildRegisterDD(regs_arg1);
  1640.     } else {
  1641.       generateKernelCall("emtime_compare");
  1642.       result.data.kind = DD_PSLCondition;
  1643.       result.abCon = buildConCon(BOOLEANINDEX);
  1644.       result.data.value.condition.psl = compareCs[opIndex-4];
  1645.       result.data.value.condition.isFloat = FALSE;
  1646.     }
  1647.       } else if (opIndex <= 11) {
  1648.     FREEV(&result);
  1649.     result = *forceIntoRegister(self, ODPBrand);
  1650.     DISCARDV(self);
  1651.     result.abCon = buildConCon(INTEGERINDEX);
  1652.     result.data = increaseIndirection(result.data);
  1653.     result.data.value.address.offset = ROData_inlineData;
  1654.     if (opIndex == 11) result.data.value.address.offset += 4;
  1655.       } else if (opIndex <= 13) {
  1656.       FREEV(&result);
  1657.       moveDataToRegister(self, regs_arg1, DataBrand);
  1658.       preemptReg(regs_scratch, 1);
  1659.       preemptReg(regs_arg2, 2);
  1660.       if (opIndex == 12) generateKernelCall("emtime_asString");
  1661.       else generateKernelCall("emtime_asDate");
  1662.       FREEV(self);
  1663.       claimReg(regs_arg1, 1, ODPBrand);
  1664.       result.data = buildRegisterDD(regs_arg1);
  1665.       result.abCon = buildConCon(STRINGINDEX);
  1666.       } else {
  1667.     unimplementedPrimitive(opIndex, typeIndex);
  1668.       }
  1669.       break;
  1670.     case INSTREAMINDEX:
  1671.       switch (opIndex) {
  1672.     case 0: /* em_read */
  1673.       moveDataToRegister(arg1, regs_arg1, DataBrand);
  1674.       moveDataToRegister(arg2, regs_arg2, ODPBrand);
  1675.       preemptReg(regs_scratch, 1);
  1676.       preemptReg(regs_arg3, 1);
  1677.       generateKernelCall("em_read");
  1678.       FREEV(arg1);
  1679.       FREEV(arg2);
  1680.       claimReg(regs_arg1, 1, DataBrand);
  1681.       result.data = buildRegisterDD(regs_arg1);
  1682.       result.abCon = buildConCon(INTEGERINDEX);
  1683.       break;
  1684.     case 1: /* em_closeInStream */
  1685.       moveDataToRegister(arg1, regs_arg1, DataBrand);
  1686.       preemptReg(regs_scratch, 1);
  1687.       preemptReg(regs_arg2, 2);
  1688.       generateKernelCall("em_closeInStream");
  1689.       FREEV(arg1);
  1690.       break;
  1691.     default:
  1692.       unimplementedPrimitive(opIndex, typeIndex);
  1693.       break;
  1694.       }
  1695.       break;
  1696.     case OUTSTREAMINDEX:
  1697.       switch (opIndex) {
  1698.     case 0: /* em_write */
  1699.       moveDataToRegister(arg1, regs_arg1, DataBrand);
  1700.       moveDataToRegister(arg2, regs_arg2, ODPBrand);
  1701.       moveDataToRegister(arg3, regs_arg3, DataBrand);
  1702.       preemptReg(regs_scratch, 1);
  1703.       generateKernelCall("em_write");
  1704.       FREEV(arg1);
  1705.       FREEV(arg2);
  1706.       FREEV(arg3);
  1707.       break;
  1708.     case 1: /* em_closeOutStream */
  1709.       moveDataToRegister(arg1, regs_arg1, DataBrand);
  1710.       preemptReg(regs_scratch, 1);
  1711.       preemptReg(regs_arg2, 2);
  1712.       generateKernelCall("em_closeOutStream");
  1713.       FREEV(arg1);
  1714.       break;
  1715.     default:
  1716.       unimplementedPrimitive(opIndex, typeIndex);
  1717.       break;
  1718.       }
  1719.       break;
  1720.     case BITCHUNKINDEX:
  1721.       switch (opIndex) {
  1722.     case 0: /* getSigned */
  1723.     case 1: /* getUnsigned */
  1724. #ifdef vax
  1725.       self = forceIntoRegister(self, ODPBrand);
  1726.       emit("\text%sv\t", opIndex == 1 ? "z" : "");
  1727.       writeDD(arg1->data, ',');
  1728.       writeDD(arg2->data, ',');
  1729.       scratch = increaseIndirection(self->data);
  1730.       scratch.value.address.offset = Vector_data;
  1731.       writeDD(scratch, ',');
  1732.       writeDD(result.data, '\n');
  1733. #endif
  1734. #ifdef sun
  1735.       /* we know that the result is a data register, if arg1 is not in a
  1736.        * register, then put it in result. */
  1737.       {
  1738.         int byteoffset = Vector_data, offset;
  1739.         if (isManifestDD(arg1->data)) {
  1740.           assert (arg1->data.kind == DD_Manifest);
  1741.           offset = arg1->data.value.manifest;
  1742.           byteoffset += ((offset / 32) * 4);
  1743.           arg1->data.value.manifest = offset % 32;
  1744.         } else {
  1745.           if (!isDataRegister(arg1->data)) {
  1746.         emitMove(arg1->data, result.data, 'l');
  1747.         arg1->data = result.data;
  1748.         eraseTempIndication(&arg1->data, result.data.value.address.offset);
  1749.           }
  1750.         }
  1751.         if (!isManifestDD(arg2->data)) {
  1752.           arg2 = forceIntoRegister(arg2, DataBrand);
  1753.         }
  1754.         self = forceIntoRegister(self, ODPBrand);
  1755.         scratch = increaseIndirection(self->data);
  1756.         scratch.value.address.offset = byteoffset;
  1757.         emit("\tbfext%s\t", opIndex == 1 ? "u" : "s");
  1758.         writeDD(scratch, '{');
  1759.         writeDD(arg1->data, ':');
  1760.         writeDD(arg2->data, '}');
  1761.         emit(",");
  1762.         writeDD(result.data, '\n');
  1763.       }
  1764. #endif      
  1765.       break;
  1766.     case 2:    /* setSigned */
  1767. #ifdef vax
  1768.       self = forceIntoRegister(self, ODPBrand);
  1769.       emit("\tinsv\t");
  1770.       writeDD(arg3->data, ',');
  1771.       writeDD(arg1->data, ',');
  1772.       writeDD(arg2->data, ',');
  1773.       scratch = increaseIndirection(self->data);
  1774.       scratch.value.address.offset = String_data;
  1775.       writeDD(scratch, '\n');
  1776. #endif
  1777. #ifdef sun
  1778.       {
  1779.         int byteoffset = Vector_data, offset, nManifest = 0;
  1780.         if (isManifestDD(arg1->data)) {
  1781.           nManifest++;
  1782.           assert (arg1->data.kind == DD_Manifest);
  1783.           offset = arg1->data.value.manifest;
  1784.           byteoffset += ((offset / 32) * 4);
  1785.           arg1->data.value.manifest = offset % 32;
  1786.         } else if (!isDataRegister(arg1->data)) {
  1787.           arg1 = forceIntoRegister(arg1, DataBrand);
  1788.         }
  1789.         if (isManifestDD(arg2->data)) {
  1790.           nManifest++;
  1791.         } else {
  1792.           arg2 = forceIntoRegister(arg2, DataBrand);
  1793.         }
  1794.         if (nManifest == 0) {
  1795.           /* we need to find another data register, steal d2 */
  1796.           emit("\tmovl\td2,sp@-\n");
  1797.           element = buildRegisterDD(6 /* d2 */);
  1798.           emitMove(arg3->data, element, 'l');
  1799.         } else {
  1800.           arg3 = forceIntoRegister(arg3, DataBrand);
  1801.           element = arg3->data;
  1802.         }
  1803.         self = forceIntoRegister(self, ODPBrand);
  1804.         emit("\tbfins\t");
  1805.         writeDD(element, ',');
  1806.         scratch = increaseIndirection(self->data);
  1807.         scratch.value.address.offset = byteoffset;
  1808.         writeDD(scratch, '{');
  1809.         writeDD(arg1->data, ':');
  1810.         writeDD(arg2->data, '}');
  1811.         emit("\n");
  1812.         if (nManifest == 0) {
  1813.           emit("\tmovl\tsp@+,d2\n");
  1814.         }
  1815.       }
  1816. #endif      
  1817.       break;
  1818.     case 3: /* addr */
  1819.       emitMove(self->data, result.data, 'l');
  1820. #ifdef sun
  1821.       emit("\taddl\t");
  1822. #endif
  1823. #ifdef vax
  1824.       emit("\taddl2\t");
  1825. #endif
  1826.       writeDD(buildManifestDD(Vector_data), ',');
  1827.       writeDD(result.data, '\n');
  1828.       break;
  1829.     
  1830.     default:
  1831.       unimplementedPrimitive(opIndex, typeIndex);
  1832.       break;
  1833.       }
  1834.       break;
  1835.     case 99:
  1836.       if (self->data.value.address.autoIncrement &&
  1837.       self->data.value.address.base == Stack &&
  1838.       self->data.value.address.offset == 0 &&
  1839.       self->abCon.value.address.autoIncrement &&
  1840.       self->abCon.value.address.base == Stack &&
  1841.       self->abCon.value.address.offset == 0) {
  1842.     /* This is a result, that must be freed, since we ignore it */
  1843. #ifdef vax
  1844.     emit("\taddl2\t$8,sp\n");
  1845. #endif
  1846. #ifdef sun
  1847.     emit("\taddqw\t#8,sp\n");
  1848. #endif
  1849.       }
  1850.       switch (opIndex) {
  1851.     case 1: /* ownName */
  1852.       FREEV(&result);
  1853.       assert (self->abCon.kind != DD_AbCon ||
  1854.         getConcreteTypeFromAbCon(self->abCon) == theObject);
  1855.       vPushOwnName(theObject);
  1856.       result = vPop();
  1857.       FREEV(self);
  1858.       break;
  1859.     case 2: /* ownType */
  1860.       FREEV(&result);
  1861.       assert (self->abCon.kind != DD_AbCon ||
  1862.         getConcreteTypeFromAbCon(self->abCon) == theObject);
  1863.       vPushOwnType(theObject);
  1864.       result = vPop();
  1865.       FREEV(self);
  1866.       break;
  1867.     default:
  1868.       unimplementedPrimitive(opIndex, typeIndex);
  1869.       break;
  1870.       }
  1871.       break;
  1872.     default:
  1873.       unimplementedPrimitive(opIndex, typeIndex);
  1874.       break;
  1875.   }
  1876.   FREEV(self);
  1877.  
  1878.   if (nargs == 0) {
  1879.   } else if (nargs == 1) {
  1880.     vDiscard();
  1881.   } else if (nargs == 2) {
  1882.     vDiscard();
  1883.     vDiscard();
  1884.   } else if (nargs == 3) {
  1885.     vDiscard();
  1886.     vDiscard();
  1887.     vDiscard();
  1888.   } else assert(FALSE);
  1889.   if (isExpression) vPush(result);
  1890.   TRACE2(primitive, 1, "End of primitive %s of type %s", 
  1891.     primOpName(typeIndex, opIndex), builtinTypeNames[typeIndex]);
  1892. }
  1893.  
  1894. /*ARGSUSED*/
  1895. void generateACPrimitive(name, nargs, isExpression, c)
  1896. char *name;
  1897. int nargs;
  1898. Boolean isExpression;
  1899. Context c;
  1900. {
  1901.   int resultRegister, i;
  1902.   Variable result;
  1903.   Variable *arg;
  1904.   DD mypusher;
  1905.   resultRegister = regs_arg1;
  1906.   result.abCon = buildConCon(INTEGERINDEX);
  1907.  
  1908. #ifdef OLDCPRIM
  1909.   assert(nargs <= 3);
  1910.   for (i = nargs; i > 0; i--) {
  1911.     arg = vPeek(0);
  1912.     moveDataToRegister(arg, i, DataBrand);
  1913.     (void) vPop();
  1914.   }
  1915.   if (nargs < 3) preemptReg(nargs+1, 3 - nargs);
  1916.   preemptReg(regs_scratch, 1);
  1917.   generateCallC(nargs, name, isExpression);
  1918.   freeReg(regs_arg1, nargs);
  1919. #else
  1920.   preemptReg(regs_arg1, 1);
  1921.   emit("\tmovl\t%s_kernelsp,%s\n", GLOBALVARINDICATOR, RN(regs_arg1));
  1922.   mypusher = pusher;
  1923.   mypusher.value.address.base = regs_arg1;
  1924.   for (i = 0; i < nargs; i++) {
  1925.     arg = vPeek(0);
  1926.     emitMove(arg->data, mypusher, 'l');
  1927.     (void) vPop();
  1928.   }
  1929.   preemptReg(regs_scratch, 1);
  1930.   generateCallC(nargs, name, isExpression);
  1931. #endif
  1932.   if (isExpression) {
  1933.     claimReg(resultRegister, 1, DataBrand);
  1934.     result.data = buildRegisterDD(resultRegister);
  1935.     vPush(result);
  1936.   }
  1937. }
  1938.  
  1939. void doPrimitive(theObject, node, pnode, self, nargs, isExpression, c)
  1940. NodePtr theObject, node, pnode;
  1941. Variable *self;
  1942. int nargs;
  1943. Boolean isExpression;
  1944. Context c;
  1945. {
  1946.   if (pnode->tag == P_INTLIT) {
  1947.     generateAMachineLanguagePrimitive(theObject, node, atoi(pnode->b.intlit.string),
  1948.       self, nargs, isExpression, c);
  1949.   } else if (pnode->tag == P_STRINGLIT) {
  1950.     /*
  1951.      * The C procedure needs to figure out for itself if "self" is a local or
  1952.      * global object.
  1953.      */
  1954.     generateACPrimitive(pnode->b.stringlit.string, nargs, isExpression, c);
  1955.   } else {
  1956.     assert(FALSE);
  1957.   }
  1958. }
  1959.